+2000-10-24 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make
+ it a static function
+
+ * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should
+ redraw text when a tag is applied to it.
+
+ * gtk/gtktexttag.c (gtk_text_tag_affects_size)
+ (gtk_text_tag_affects_nonsize_appearance): private functions to
+ see if a tag requires various kinds of redraw/layout to be queued
+ up.
+
+ * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock
+
+ * gtk/testtext.c (fill_example_buffer): Put the cursor
+ at the start of the buffer, so search works by default
+
+ * gtk/gtktextiter.c (lines_match): init match_start always
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New
+ function, get iter at a line + a byte index
+
+ * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function,
+ to set byte position within a line
+ (gtk_text_iter_check): remove leftover G_BREAKPOINT thing
+
2000-10-23 Havoc Pennington <hp@redhat.com>
* gtk/testtext.c: Re-enable the "find" dialog
+2000-10-24 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make
+ it a static function
+
+ * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should
+ redraw text when a tag is applied to it.
+
+ * gtk/gtktexttag.c (gtk_text_tag_affects_size)
+ (gtk_text_tag_affects_nonsize_appearance): private functions to
+ see if a tag requires various kinds of redraw/layout to be queued
+ up.
+
+ * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock
+
+ * gtk/testtext.c (fill_example_buffer): Put the cursor
+ at the start of the buffer, so search works by default
+
+ * gtk/gtktextiter.c (lines_match): init match_start always
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New
+ function, get iter at a line + a byte index
+
+ * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function,
+ to set byte position within a line
+ (gtk_text_iter_check): remove leftover G_BREAKPOINT thing
+
2000-10-23 Havoc Pennington <hp@redhat.com>
* gtk/testtext.c: Re-enable the "find" dialog
+2000-10-24 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make
+ it a static function
+
+ * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should
+ redraw text when a tag is applied to it.
+
+ * gtk/gtktexttag.c (gtk_text_tag_affects_size)
+ (gtk_text_tag_affects_nonsize_appearance): private functions to
+ see if a tag requires various kinds of redraw/layout to be queued
+ up.
+
+ * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock
+
+ * gtk/testtext.c (fill_example_buffer): Put the cursor
+ at the start of the buffer, so search works by default
+
+ * gtk/gtktextiter.c (lines_match): init match_start always
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New
+ function, get iter at a line + a byte index
+
+ * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function,
+ to set byte position within a line
+ (gtk_text_iter_check): remove leftover G_BREAKPOINT thing
+
2000-10-23 Havoc Pennington <hp@redhat.com>
* gtk/testtext.c: Re-enable the "find" dialog
+2000-10-24 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make
+ it a static function
+
+ * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should
+ redraw text when a tag is applied to it.
+
+ * gtk/gtktexttag.c (gtk_text_tag_affects_size)
+ (gtk_text_tag_affects_nonsize_appearance): private functions to
+ see if a tag requires various kinds of redraw/layout to be queued
+ up.
+
+ * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock
+
+ * gtk/testtext.c (fill_example_buffer): Put the cursor
+ at the start of the buffer, so search works by default
+
+ * gtk/gtktextiter.c (lines_match): init match_start always
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New
+ function, get iter at a line + a byte index
+
+ * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function,
+ to set byte position within a line
+ (gtk_text_iter_check): remove leftover G_BREAKPOINT thing
+
2000-10-23 Havoc Pennington <hp@redhat.com>
* gtk/testtext.c: Re-enable the "find" dialog
+2000-10-24 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make
+ it a static function
+
+ * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should
+ redraw text when a tag is applied to it.
+
+ * gtk/gtktexttag.c (gtk_text_tag_affects_size)
+ (gtk_text_tag_affects_nonsize_appearance): private functions to
+ see if a tag requires various kinds of redraw/layout to be queued
+ up.
+
+ * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock
+
+ * gtk/testtext.c (fill_example_buffer): Put the cursor
+ at the start of the buffer, so search works by default
+
+ * gtk/gtktextiter.c (lines_match): init match_start always
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New
+ function, get iter at a line + a byte index
+
+ * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function,
+ to set byte position within a line
+ (gtk_text_iter_check): remove leftover G_BREAKPOINT thing
+
2000-10-23 Havoc Pennington <hp@redhat.com>
* gtk/testtext.c: Re-enable the "find" dialog
+2000-10-24 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make
+ it a static function
+
+ * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should
+ redraw text when a tag is applied to it.
+
+ * gtk/gtktexttag.c (gtk_text_tag_affects_size)
+ (gtk_text_tag_affects_nonsize_appearance): private functions to
+ see if a tag requires various kinds of redraw/layout to be queued
+ up.
+
+ * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock
+
+ * gtk/testtext.c (fill_example_buffer): Put the cursor
+ at the start of the buffer, so search works by default
+
+ * gtk/gtktextiter.c (lines_match): init match_start always
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New
+ function, get iter at a line + a byte index
+
+ * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function,
+ to set byte position within a line
+ (gtk_text_iter_check): remove leftover G_BREAKPOINT thing
+
2000-10-23 Havoc Pennington <hp@redhat.com>
* gtk/testtext.c: Re-enable the "find" dialog
+2000-10-24 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktextview.c (gtk_text_view_scroll_to_mark_adjusted): make
+ it a static function
+
+ * gtk/gtktextbtree.c (gtk_text_btree_tag): Gee, maybe we should
+ redraw text when a tag is applied to it.
+
+ * gtk/gtktexttag.c (gtk_text_tag_affects_size)
+ (gtk_text_tag_affects_nonsize_appearance): private functions to
+ see if a tag requires various kinds of redraw/layout to be queued
+ up.
+
+ * gtk/gtktexttag.h (struct _GtkTextTag): Remove relief crackrock
+
+ * gtk/testtext.c (fill_example_buffer): Put the cursor
+ at the start of the buffer, so search works by default
+
+ * gtk/gtktextiter.c (lines_match): init match_start always
+
+ * gtk/gtktextbuffer.c (gtk_text_buffer_get_iter_at_line_index): New
+ function, get iter at a line + a byte index
+
+ * gtk/gtktextiter.c (gtk_text_iter_set_line_index): New function,
+ to set byte position within a line
+ (gtk_text_iter_check): remove leftover G_BREAKPOINT thing
+
2000-10-23 Havoc Pennington <hp@redhat.com>
* gtk/testtext.c: Re-enable the "find" dialog
+2000-10-24 Havoc Pennington <hp@redhat.com>
+
+ * gtk/text_widget.sgml: add note about UTF-8
+
2000-10-23 Havoc Pennington <hp@redhat.com>
* gtk/gtk-sections.txt: remove GtkTextBTree
displayed by any number of views.
</para>
+<para>
+One of the important things to remember about text in GTK+ is that it's in the
+UTF-8 encoding. This means that one character can be encoded as multiple
+bytes. Character counts are usually referred to as
+<firstterm>offsets</firstterm>, while byte counts are called
+<firstterm>indexes</firstterm>. If you confuse these two, things will work fine
+with ASCII, but as soon as your buffer contains multibyte characters, bad things
+will happen.
+</para>
+
<para>
Text in a buffer can be marked with <firstterm>tags</firstterm>. A tag is an
attribute that can be applied to some range of text. For example, a tag might be
GtkTextTagTable *table;
GHashTable *mark_table;
guint refcount;
- GtkTextLineSegment *insert_mark;
- GtkTextLineSegment *selection_bound_mark;
+ GtkTextMark *insert_mark;
+ GtkTextMark *selection_bound_mark;
GtkTextBuffer *buffer;
BTreeView *views;
GSList *tag_infos;
static void gtk_text_btree_remove_tag_info (GtkTextBTree *tree,
GtkTextTag *tag);
+static void redisplay_region (GtkTextBTree *tree,
+ const GtkTextIter *start,
+ const GtkTextIter *end);
/* Inline thingies */
{
GtkTextIter start;
-
+ GtkTextLineSegment *seg;
+
gtk_text_btree_get_iter_at_line_char(tree, &start, 0, 0);
- tree->insert_mark =
- (GtkTextLineSegment*) gtk_text_btree_set_mark(tree,
- NULL,
- "insert",
- FALSE,
- &start,
- FALSE);
+ tree->insert_mark = gtk_text_btree_set_mark (tree,
+ NULL,
+ "insert",
+ FALSE,
+ &start,
+ FALSE);
+
+ seg = tree->insert_mark->segment;
- tree->insert_mark->body.mark.not_deleteable = TRUE;
- tree->insert_mark->body.mark.visible = TRUE;
+ seg->body.mark.not_deleteable = TRUE;
+ seg->body.mark.visible = TRUE;
- tree->selection_bound_mark =
- (GtkTextLineSegment*) gtk_text_btree_set_mark(tree,
- NULL,
- "selection_bound",
- FALSE,
- &start,
- FALSE);
-
- tree->selection_bound_mark->body.mark.not_deleteable = TRUE;
+ tree->selection_bound_mark = gtk_text_btree_set_mark (tree,
+ NULL,
+ "selection_bound",
+ FALSE,
+ &start,
+ FALSE);
+
+ seg = tree->selection_bound_mark->segment;
- _mark_segment_ref(tree->insert_mark);
- _mark_segment_ref(tree->selection_bound_mark);
+ seg->body.mark.not_deleteable = TRUE;
+
+ g_object_ref (G_OBJECT (tree->insert_mark));
+ g_object_ref (G_OBJECT (tree->selection_bound_mark));
}
tree->refcount = 1;
static void
mark_destroy_foreach (gpointer key, gpointer value, gpointer user_data)
{
- _mark_segment_unref (value);
+ GtkTextLineSegment *seg = value;
+
+ g_return_if_fail (seg->body.mark.tree == NULL);
+
+ g_object_unref (G_OBJECT (seg->body.mark.obj));
}
void
tree->refcount -= 1;
if (tree->refcount == 0)
- {
- gtk_text_btree_node_destroy(tree, tree->root_node);
+ {
+ gtk_text_btree_node_destroy (tree, tree->root_node);
- g_hash_table_foreach(tree->mark_table,
- mark_destroy_foreach,
- NULL);
- g_hash_table_destroy(tree->mark_table);
+ g_hash_table_foreach (tree->mark_table,
+ mark_destroy_foreach,
+ NULL);
+ g_hash_table_destroy (tree->mark_table);
- _mark_segment_unref(tree->insert_mark);
- _mark_segment_unref(tree->selection_bound_mark);
+ g_object_unref (G_OBJECT (tree->insert_mark));
+ g_object_unref (G_OBJECT (tree->selection_bound_mark));
- gtk_signal_disconnect(GTK_OBJECT(tree->table),
- tree->tag_changed_handler);
+ gtk_signal_disconnect (GTK_OBJECT(tree->table),
+ tree->tag_changed_handler);
- gtk_signal_disconnect(GTK_OBJECT(tree->table),
- tree->tag_removed_handler);
+ gtk_signal_disconnect (GTK_OBJECT(tree->table),
+ tree->tag_removed_handler);
- gtk_object_unref(GTK_OBJECT(tree->table));
+ gtk_object_unref (GTK_OBJECT(tree->table));
- g_free(tree);
+ g_free (tree);
}
}
g_return_if_fail(tree != NULL);
g_return_if_fail(view_id != NULL);
- gtk_text_btree_node_get_size(tree->root_node, view_id,
- width, height);
+ gtk_text_btree_node_get_size (tree->root_node, view_id,
+ width, height);
}
/*
}
}
+static void
+queue_tag_redisplay (GtkTextBTree *tree,
+ GtkTextTag *tag,
+ const GtkTextIter *start,
+ const GtkTextIter *end)
+{
+ if (gtk_text_tag_affects_size (tag))
+ {
+ gtk_text_btree_invalidate_region (tree, start, end);
+
+ }
+ else if (gtk_text_tag_affects_nonsize_appearance (tag))
+ {
+ /* We only need to queue a redraw, not a relayout */
+ redisplay_region (tree, start, end);
+ }
+
+ /* We don't need to do anything if the tag doesn't affect display */
+}
+
void
gtk_text_btree_tag (const GtkTextIter *start_orig,
const GtkTextIter *end_orig,
tree = gtk_text_iter_get_btree(&start);
+ queue_tag_redisplay (tree, tag, &start, &end);
+
info = gtk_text_btree_get_tag_info(tree, tag);
start_line = gtk_text_iter_get_text_line(&start);
if (ld)
end_y += ld->height;
- gtk_text_layout_changed (view->layout, start_y, end_y - start_y, end_y - start_y);
+ gtk_text_layout_changed (view->layout, start_y,
+ end_y - start_y,
+ end_y - start_y);
view = view->next;
}
}
static void
-redisplay_mark(GtkTextLineSegment *mark)
+redisplay_mark (GtkTextLineSegment *mark)
{
GtkTextIter iter;
GtkTextIter end;
gtk_text_btree_get_iter_at_mark(mark->body.mark.tree,
&iter,
- (GtkTextMark*)mark);
+ mark->body.mark.obj);
end = iter;
gtk_text_iter_next_char(&end);
g_return_val_if_fail(gtk_text_iter_get_btree(where) == tree, NULL);
if (existing_mark)
- mark = (GtkTextLineSegment*) existing_mark;
+ mark = existing_mark->segment;
else if (name != NULL)
- mark = g_hash_table_lookup(tree->mark_table,
- name);
+ mark = g_hash_table_lookup (tree->mark_table,
+ name);
else
mark = NULL;
if (mark != NULL)
{
if (redraw_selections &&
- (mark == tree->insert_mark ||
- mark == tree->selection_bound_mark))
+ (mark == tree->insert_mark->segment ||
+ mark == tree->selection_bound_mark->segment))
{
GtkTextIter old_pos;
- gtk_text_btree_get_iter_at_mark (tree, &old_pos, (GtkTextMark*)mark);
+ gtk_text_btree_get_iter_at_mark (tree, &old_pos,
+ mark->body.mark.obj);
redisplay_region (tree, &old_pos, where);
}
}
/* Redraw the mark's old location. */
- redisplay_mark_if_visible(mark);
+ redisplay_mark_if_visible (mark);
/* Unlink mark from its current location.
This could hose our iterator... */
mark->body.mark.line = gtk_text_iter_get_text_line(&iter);
if (mark->body.mark.name)
- g_hash_table_insert(tree->mark_table,
- mark->body.mark.name,
- mark);
+ g_hash_table_insert (tree->mark_table,
+ mark->body.mark.name,
+ mark);
}
/* Link mark into new location */
- gtk_text_btree_link_segment(mark, &iter);
+ gtk_text_btree_link_segment (mark, &iter);
/* Invalidate some iterators. */
- segments_changed(tree);
+ segments_changed (tree);
/*
* update the screen at the mark's new location.
*/
- redisplay_mark_if_visible(mark);
+ redisplay_mark_if_visible (mark);
return mark;
}
const GtkTextIter *iter,
gboolean should_exist)
{
- return (GtkTextMark*)real_set_mark(tree, existing_mark,
- name, left_gravity, iter, should_exist,
- TRUE);
+ GtkTextLineSegment *seg;
+
+ seg = real_set_mark(tree, existing_mark,
+ name, left_gravity, iter, should_exist,
+ TRUE);
+
+ return seg ? seg->body.mark.obj : NULL;
}
gboolean
GtkTextIter tmp_start, tmp_end;
gtk_text_btree_get_iter_at_mark (tree, &tmp_start,
- (GtkTextMark*)tree->insert_mark);
+ tree->insert_mark);
gtk_text_btree_get_iter_at_mark (tree, &tmp_end,
- (GtkTextMark*)tree->selection_bound_mark);
+ tree->selection_bound_mark);
if (gtk_text_iter_equal(&tmp_start, &tmp_end))
{
redisplay_region(tree, &start, &end);
/* Move insert AND selection_bound before we redisplay */
- real_set_mark(tree, (GtkTextMark*) tree->insert_mark,
- "insert", FALSE, iter, TRUE, FALSE);
- real_set_mark(tree, (GtkTextMark*) tree->selection_bound_mark,
- "selection_bound", FALSE, iter, TRUE, FALSE);
+ real_set_mark (tree, tree->insert_mark,
+ "insert", FALSE, iter, TRUE, FALSE);
+ real_set_mark (tree, tree->selection_bound_mark,
+ "selection_bound", FALSE, iter, TRUE, FALSE);
}
void
gtk_text_btree_remove_mark (GtkTextBTree *tree,
GtkTextMark *mark)
{
- GtkTextLineSegment *segment = (GtkTextLineSegment*) mark;
+ GtkTextLineSegment *segment;
- g_return_if_fail (segment != NULL);
+ g_return_if_fail (mark != NULL);
g_return_if_fail (tree != NULL);
+ segment = mark->segment;
+
if (segment->body.mark.not_deleteable)
{
g_warning("Can't delete special mark `%s'", segment->body.mark.name);
if (segment->body.mark.name)
g_hash_table_remove (tree->mark_table, segment->body.mark.name);
-
- _mark_segment_unref (segment);
+
+ /* Remove the ref on the mark that belonged to the segment. */
+ g_object_unref (G_OBJECT (mark));
segment->body.mark.tree = NULL;
segment->body.mark.line = NULL;
gtk_text_btree_mark_is_insert (GtkTextBTree *tree,
GtkTextMark *segment)
{
- return segment == (GtkTextMark*) tree->insert_mark;
+ return segment == tree->insert_mark;
}
gboolean
gtk_text_btree_mark_is_selection_bound (GtkTextBTree *tree,
GtkTextMark *segment)
{
- return segment == (GtkTextMark*) tree->selection_bound_mark;
+ return segment == tree->selection_bound_mark;
}
GtkTextMark*
gtk_text_btree_get_mark_by_name (GtkTextBTree *tree,
const gchar *name)
{
+ GtkTextLineSegment *seg;
+
g_return_val_if_fail(tree != NULL, NULL);
g_return_val_if_fail(name != NULL, NULL);
- return g_hash_table_lookup(tree->mark_table, name);
+ seg = g_hash_table_lookup (tree->mark_table, name);
+
+ return seg ? seg->body.mark.obj : NULL;
}
void
g_return_if_fail(mark != NULL);
- seg = (GtkTextLineSegment*)mark;
+ seg = mark->segment;
if (seg->body.mark.visible == setting)
return;
{
seg = line->segments;
line->segments = seg->next;
- (*seg->type->deleteFunc)(seg, line, 1);
+
+ if (GTK_IS_TEXT_MARK_SEGMENT (seg))
+ {
+ /* Set the mark as deleted */
+ seg->body.mark.tree = NULL;
+ seg->body.mark.line = NULL;
+ }
+
+ (*seg->type->deleteFunc) (seg, line, 1);
}
gtk_text_line_destroy(tree, line);
}
{
childPtr = node->children.node;
node->children.node = childPtr->next;
- gtk_text_btree_node_destroy(tree, childPtr);
+ gtk_text_btree_node_destroy (tree, childPtr);
}
}
- summary_list_destroy(node->summary);
- node_data_list_destroy(node->node_data);
- g_free(node);
+
+ summary_list_destroy (node->summary);
+ node_data_list_destroy (node->node_data);
+ g_free (node);
}
static NodeData*
}
static void
-tag_changed_cb(GtkTextTagTable *table,
- GtkTextTag *tag,
- gboolean size_changed,
- GtkTextBTree *tree)
+tag_changed_cb (GtkTextTagTable *table,
+ GtkTextTag *tag,
+ gboolean size_changed,
+ GtkTextBTree *tree)
{
if (size_changed)
{
- /* We need to queue a redisplay on all regions that are tagged with
- this tag. */
+ /* We need to queue a relayout on all regions that are tagged with
+ * this tag.
+ */
GtkTextIter start;
GtkTextIter end;
if (gtk_text_btree_get_iter_at_first_toggle(tree, &start, tag))
{
/* Must be a last toggle if there was a first one. */
- gtk_text_btree_get_iter_at_last_toggle(tree, &end, tag);
- gtk_text_btree_invalidate_region(tree,
- &start, &end);
+ gtk_text_btree_get_iter_at_last_toggle (tree, &end, tag);
+ gtk_text_btree_invalidate_region (tree,
+ &start, &end);
}
}
else
{
+ /* We only need to queue a redraw, not a relayout */
BTreeView *view;
view = tree->views;
this signal is purely for notification, and not to allow users
to modify the default behavior. */
- gtk_text_mark_ref (mark);
+ g_object_ref (G_OBJECT (mark));
gtk_signal_emit(GTK_OBJECT(buffer),
signals[MARK_SET],
location,
mark);
- gtk_text_mark_unref (mark);
+ g_object_unref (G_OBJECT (mark));
}
/**
GtkTextIter location;
GtkTextMark *mark;
- mark = gtk_text_btree_set_mark(get_btree (buffer),
- existing_mark,
- mark_name,
- left_gravity,
- iter,
- should_exist);
+ mark = gtk_text_btree_set_mark (get_btree (buffer),
+ existing_mark,
+ mark_name,
+ left_gravity,
+ iter,
+ should_exist);
if (gtk_text_btree_mark_is_insert(get_btree (buffer), mark) ||
gtk_text_btree_mark_is_selection_bound (get_btree (buffer), mark))
gtk_text_buffer_mark_set (buffer, &location, mark);
- return (GtkTextMark*)mark;
+ return mark;
}
/**
GtkTextMark *mark,
const GtkTextIter *where)
{
- g_return_if_fail (mark != NULL);
+ g_return_if_fail (GTK_IS_TEXT_MARK (mark));
g_return_if_fail (!gtk_text_mark_get_deleted (mark));
g_return_if_fail (GTK_IS_TEXT_BUFFER(buffer));
GtkTextIter *iter,
GtkTextMark *mark)
{
- g_return_if_fail (mark != NULL);
+ g_return_if_fail (GTK_IS_TEXT_MARK (mark));
g_return_if_fail (!gtk_text_mark_get_deleted (mark));
g_return_if_fail (GTK_IS_TEXT_BUFFER(buffer));
*
* Deletes @mark, so that it's no longer located anywhere in the
* buffer. Removes the reference the buffer holds to the mark, so if
- * you haven't called gtk_text_mark_ref() the mark will be freed. Even
+ * you haven't called g_object_ref() on the mark, it will be freed. Even
* if the mark isn't freed, most operations on @mark become
* invalid. There is no way to undelete a
* mark. gtk_text_mark_get_deleted() will return TRUE after this
gtk_text_buffer_delete_mark(GtkTextBuffer *buffer,
GtkTextMark *mark)
{
- g_return_if_fail (mark != NULL);
+ g_return_if_fail (GTK_IS_TEXT_MARK (mark));
g_return_if_fail (!gtk_text_mark_get_deleted (mark));
g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
- gtk_text_mark_ref (mark);
+ g_object_ref (G_OBJECT (mark));
gtk_text_btree_remove_mark (get_btree (buffer), mark);
gtk_signal_emit (GTK_OBJECT(buffer), signals[MARK_DELETED],
mark);
- gtk_text_mark_unref (mark);
+ g_object_unref (G_OBJECT (mark));
}
/**
gint line_number,
gint char_offset)
{
- g_return_if_fail(iter != NULL);
- g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (GTK_IS_TEXT_BUFFER(buffer));
+
+ gtk_text_btree_get_iter_at_line_char (get_btree (buffer),
+ iter, line_number, char_offset);
+}
+
+void
+gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ gint line_number,
+ gint byte_index)
+{
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (GTK_IS_TEXT_BUFFER(buffer));
- gtk_text_btree_get_iter_at_line_char(get_btree (buffer),
- iter, line_number, char_offset);
+ gtk_text_btree_get_iter_at_line_byte (get_btree (buffer),
+ iter, line_number, byte_index);
}
void
GtkTextIter *iter,
gint line_number,
gint char_offset);
+void gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ gint line_number,
+ gint byte_index);
void gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer,
GtkTextIter *iter,
gint char_offset);
seg = seg->next;
}
- iter_set_from_byte_offset(iter, line, byte_offset);
+ iter_set_from_byte_offset (iter, line, byte_offset);
}
/* This function ensures that the segment-dependent information is
* Return value: distance from start of line, in bytes
**/
gint
-gtk_text_iter_get_line_index(const GtkTextIter *iter)
+gtk_text_iter_get_line_index (const GtkTextIter *iter)
{
GtkTextRealIter *real;
{
if (seg->type == >k_text_left_mark_type ||
seg->type == >k_text_right_mark_type)
- retval = g_slist_prepend(retval, (GtkTextMark*)seg);
+ retval = g_slist_prepend (retval, seg->body.mark.obj);
seg = seg->next;
}
}
void
-gtk_text_iter_set_line(GtkTextIter *iter, gint line_number)
+gtk_text_iter_set_line_index (GtkTextIter *iter,
+ gint byte_on_line)
+{
+ GtkTextRealIter *real;
+
+ g_return_if_fail (iter != NULL);
+
+ real = gtk_text_iter_make_surreal (iter);
+
+ if (real == NULL)
+ return;
+
+ check_invariants (iter);
+
+ iter_set_from_byte_offset (real, real->line, byte_on_line);
+
+ if (real->segment->type == >k_text_char_type &&
+ (real->segment->body.chars[real->segment_byte_offset] & 0xc0) == 0x80)
+ g_warning ("%s: Incorrect byte offset %d falls in the middle of a UTF-8 "
+ "character; this will crash the text buffer. "
+ "Byte indexes must refer to the start of a character.",
+ G_STRLOC, byte_on_line);
+
+ check_invariants (iter);
+}
+
+void
+gtk_text_iter_set_line (GtkTextIter *iter,
+ gint line_number)
{
GtkTextLine *line;
gint real_line;
if (*lines == NULL || **lines == '\0')
{
+ if (match_start)
+ *match_start = *start;
+
if (match_end)
*match_end = *start;
return TRUE;
}
if (found == NULL)
- {
+ {
g_free (line_text);
return FALSE;
}
forward_chars_with_skipping (match_start, offset,
visible_only, !slice);
}
-
+
/* Go to end of search string */
offset += g_utf8_strlen (*lines, -1);
void
gtk_text_btree_get_iter_at_line_byte (GtkTextBTree *tree,
- GtkTextIter *iter,
- gint line_number,
- gint byte_index)
+ GtkTextIter *iter,
+ gint line_number,
+ gint byte_index)
{
GtkTextRealIter *real = (GtkTextRealIter*)iter;
GtkTextLine *line;
/* We might as well cache this, since we know it. */
real->cached_line_number = real_line;
+ if (real->segment->type == >k_text_char_type &&
+ (real->segment->body.chars[real->segment_byte_offset] & 0xc0) == 0x80)
+ g_warning ("%s: Incorrect byte offset %d falls in the middle of a UTF-8 "
+ "character; this will crash the text buffer. "
+ "Byte indexes must refer to the start of a character.",
+ G_STRLOC, byte_index);
+
check_invariants(iter);
}
g_return_val_if_fail(iter != NULL, FALSE);
g_return_val_if_fail(tree != NULL, FALSE);
- mark = gtk_text_btree_get_mark_by_name(tree, mark_name);
+ mark = gtk_text_btree_get_mark_by_name (tree, mark_name);
if (mark == NULL)
return FALSE;
else
{
- gtk_text_btree_get_iter_at_mark(tree, iter, mark);
- check_invariants(iter);
+ gtk_text_btree_get_iter_at_mark (tree, iter, mark);
+ check_invariants (iter);
return TRUE;
}
}
void
gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
- GtkTextIter *iter,
- GtkTextMark *mark)
+ GtkTextIter *iter,
+ GtkTextMark *mark)
{
- GtkTextLineSegment *seg = (GtkTextLineSegment*) mark;
+ GtkTextLineSegment *seg;
- g_return_if_fail(iter != NULL);
- g_return_if_fail(tree != NULL);
- g_return_if_fail(GTK_IS_TEXT_MARK (mark));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (tree != NULL);
+ g_return_if_fail (GTK_IS_TEXT_MARK (mark));
+
+ seg = mark->segment;
- iter_init_from_segment(iter, tree,
- seg->body.mark.line, seg);
- g_assert(seg->body.mark.line == gtk_text_iter_get_text_line(iter));
+ iter_init_from_segment (iter, tree,
+ seg->body.mark.line, seg);
+ g_assert (seg->body.mark.line == gtk_text_iter_get_text_line(iter));
check_invariants(iter);
}
real->line_byte_offset,
real->line_char_offset);
#endif
-
- if (real->line_byte_offset == 97 &&
- real->line_char_offset == 95)
- G_BREAKPOINT();
if (segments_updated)
{
gint line_number);
void gtk_text_iter_set_line_offset (GtkTextIter *iter,
gint char_on_line);
+void gtk_text_iter_set_line_index (GtkTextIter *iter,
+ gint byte_on_line);
void gtk_text_iter_forward_to_end (GtkTextIter *iter);
gboolean gtk_text_iter_forward_to_newline (GtkTextIter *iter);
* user has hidden the cursor.
*/
if (gtk_text_btree_mark_is_insert (_gtk_text_buffer_get_btree (layout->buffer),
- (GtkTextMark*)seg) &&
+ seg->body.mark.obj) &&
(!layout->cursor_visible ||
gtk_text_buffer_get_selection_bounds (layout->buffer, NULL, NULL)))
return;
#include "gtktextbtree.h"
-gboolean
-gtk_text_mark_is_visible(GtkTextMark *mark)
+static void gtk_text_mark_init (GtkTextMark *mark);
+static void gtk_text_mark_class_init (GtkTextMarkClass *klass);
+static void gtk_text_mark_finalize (GObject *obj);
+
+
+static gpointer parent_class = NULL;
+
+GType
+gtk_text_mark_get_type (void)
{
- GtkTextLineSegment *seg;
+ static GType object_type = 0;
- seg = (GtkTextLineSegment*)mark;
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (GtkTextMarkClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gtk_text_mark_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GtkTextMark),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gtk_text_mark_init,
+ };
+
+ object_type = g_type_register_static (G_TYPE_OBJECT,
+ "GtkTextMark",
+ &object_info);
+ }
+
+ return object_type;
+}
- return seg->body.mark.visible;
+static void
+gtk_text_mark_init (GtkTextMark *mark)
+{
+ mark->segment = NULL;
}
-const char *
-gtk_text_mark_get_name (GtkTextMark *mark)
+static void
+gtk_text_mark_class_init (GtkTextMarkClass *klass)
{
- GtkTextLineSegment *seg;
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- seg = (GtkTextLineSegment*)mark;
+ parent_class = g_type_class_peek_parent (klass);
- return seg->body.mark.name;
+ object_class->finalize = gtk_text_mark_finalize;
}
-
-GtkTextMark *
-gtk_text_mark_ref (GtkTextMark *mark)
+static void
+gtk_text_mark_finalize (GObject *obj)
{
+ GtkTextMark *mark;
GtkTextLineSegment *seg;
- seg = (GtkTextLineSegment*)mark;
+ mark = GTK_TEXT_MARK (obj);
- _mark_segment_ref (seg);
+ seg = mark->segment;
- return mark;
+ if (seg)
+ {
+ g_return_if_fail (seg->body.mark.tree == NULL);
+
+ if (seg->body.mark.tree != NULL)
+ g_warning ("GtkTextMark being finalized while still in the buffer; "
+ "someone removed a reference they didn't own! Crash "
+ "impending");
+
+ g_free (seg->body.mark.name);
+ g_free (seg);
+
+ mark->segment = NULL;
+ }
}
-void
-gtk_text_mark_unref (GtkTextMark *mark)
+gboolean
+gtk_text_mark_is_visible(GtkTextMark *mark)
{
GtkTextLineSegment *seg;
- seg = (GtkTextLineSegment*)mark;
-
- _mark_segment_unref (seg);
+ seg = mark->segment;
+
+ return seg->body.mark.visible;
+}
+
+const char *
+gtk_text_mark_get_name (GtkTextMark *mark)
+{
+ GtkTextLineSegment *seg;
+
+ seg = mark->segment;
+
+ return seg->body.mark.name;
}
gboolean
g_return_val_if_fail (mark != NULL, FALSE);
- seg = (GtkTextLineSegment*)mark;
+ seg = mark->segment;
+
+ if (seg == NULL)
+ return TRUE;
return seg->body.mark.tree == NULL;
}
mark->type = >k_text_left_mark_type;
else
mark->type = >k_text_right_mark_type;
-
+
mark->byte_count = 0;
mark->char_count = 0;
+ mark->body.mark.obj = g_object_new (GTK_TYPE_TEXT_MARK, NULL);
+ mark->body.mark.obj->segment = mark;
+
mark->body.mark.tree = tree;
mark->body.mark.line = NULL;
mark->next = NULL;
- mark->body.mark.refcount = 1;
-
mark->body.mark.visible = FALSE;
mark->body.mark.not_deleteable = FALSE;
return mark;
}
-void
-_mark_segment_ref (GtkTextLineSegment *mark)
-{
- g_return_if_fail (mark != NULL);
- g_return_if_fail (mark->type == >k_text_right_mark_type ||
- mark->type == >k_text_left_mark_type);
- g_return_if_fail (mark->body.mark.refcount > 0);
-
- mark->body.mark.refcount += 1;
-}
-
-void
-_mark_segment_unref (GtkTextLineSegment *mark)
-{
- g_return_if_fail (mark != NULL);
- g_return_if_fail (mark->type == >k_text_right_mark_type ||
- mark->type == >k_text_left_mark_type);
- g_return_if_fail (mark->body.mark.refcount > 0);
-
- mark->body.mark.refcount -= 1;
-
- if (mark->body.mark.refcount == 0)
- {
- g_free(mark->body.mark.name);
-
- g_free(mark);
- }
-}
-
-
static int mark_segment_delete_func (GtkTextLineSegment *segPtr,
GtkTextLine *line,
int treeGone);
/* The GtkTextMark data type */
-typedef struct _GtkTextMark GtkTextMark;
+typedef struct _GtkTextMark GtkTextMark;
+typedef struct _GtkTextMarkClass GtkTextMarkClass;
+
+#define GTK_TYPE_TEXT_MARK (gtk_text_mark_get_type ())
+#define GTK_TEXT_MARK(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_TEXT_MARK, GtkTextMark))
+#define GTK_TEXT_MARK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TEXT_MARK, GtkTextMarkClass))
+#define GTK_IS_TEXT_MARK(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_TEXT_MARK))
+#define GTK_IS_TEXT_MARK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TEXT_MARK))
+#define GTK_TEXT_MARK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TEXT_MARK, GtkTextMarkClass))
+
+struct _GtkTextMark
+{
+ GObject parent_instance;
+
+ gpointer segment;
+};
+
+struct _GtkTextMarkClass
+{
+ GObjectClass parent_class;
+
+};
+
+GType gtk_text_mark_get_type (void) G_GNUC_CONST;
void gtk_text_mark_set_visible (GtkTextMark *mark,
gboolean setting);
gboolean gtk_text_mark_is_visible (GtkTextMark *mark);
/* FIXME gconst */
-const char * gtk_text_mark_get_name (GtkTextMark *mark);
-GtkTextMark *gtk_text_mark_ref (GtkTextMark *mark);
-void gtk_text_mark_unref (GtkTextMark *mark);
+const char *gtk_text_mark_get_name (GtkTextMark *mark);
gboolean gtk_text_mark_get_deleted (GtkTextMark *mark);
#include <gtk/gtktexttypes.h>
#include <gtk/gtktextlayout.h>
-#define GTK_IS_TEXT_MARK(mark) (((GtkTextLineSegment*)mark)->type == >k_text_left_mark_type || \
+#define GTK_IS_TEXT_MARK_SEGMENT(mark) (((GtkTextLineSegment*)mark)->type == >k_text_left_mark_type || \
((GtkTextLineSegment*)mark)->type == >k_text_right_mark_type)
/*
*/
struct _GtkTextMarkBody {
- guint refcount;
+ GtkTextMark *obj;
gchar *name;
GtkTextBTree *tree;
GtkTextLine *line;
GtkTextLineSegment *_mark_segment_new (GtkTextBTree *tree,
gboolean left_gravity,
const gchar *name);
-void _mark_segment_ref (GtkTextLineSegment *mark);
-void _mark_segment_unref (GtkTextLineSegment *mark);
-
#ifdef __cplusplus
}
dest->appearance.bg_color = vals->appearance.bg_color;
dest->appearance.draw_bg = TRUE;
- }
-
- if (tag->relief_set)
- dest->relief = vals->relief;
+ }
if (tag->bg_stipple_set)
{
++n;
}
}
+
+gboolean
+gtk_text_tag_affects_size (GtkTextTag *tag)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
+
+ return
+ tag->font_set ||
+ tag->justify_set ||
+ tag->left_margin_set ||
+ tag->left_wrapped_line_margin_set ||
+ tag->offset_set ||
+ tag->right_margin_set ||
+ tag->pixels_above_lines_set ||
+ tag->pixels_below_lines_set ||
+ tag->pixels_inside_wrap_set ||
+ tag->tabs_set ||
+ tag->underline_set ||
+ tag->wrap_mode_set ||
+ tag->invisible_set;
+}
+
+gboolean
+gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
+
+ return
+ tag->bg_color_set ||
+ tag->bg_stipple_set ||
+ tag->fg_color_set ||
+ tag->fg_stipple_set ||
+ tag->strikethrough_set ||
+ tag->bg_full_height_set;
+}
typedef struct _GtkTextTag GtkTextTag;
typedef struct _GtkTextTagClass GtkTextTagClass;
-struct _GtkTextTag {
+struct _GtkTextTag
+{
GtkObject parent_instance;
GtkTextTagTable *table;
* this tag does not affect it.
*/
guint bg_color_set : 1;
- guint relief_set : 1;
guint bg_stipple_set : 1;
guint fg_color_set : 1;
guint font_set : 1;
GtkTextAppearance appearance;
- GtkShadowType relief;
GtkJustification justify;
GtkTextDirection direction;
GdkColormap *cmap,
GdkVisual *visual);
+gboolean gtk_text_tag_affects_size (GtkTextTag *tag);
+gboolean gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag);
+
#endif
GdkPixbuf *pixbuf;
int i;
char *str;
+
+ /* FIXME this is broken if called twice on a buffer, since
+ * we try to create tags a second time.
+ */
tag = gtk_text_buffer_create_tag (buffer, "fg_blue");
g_object_unref (G_OBJECT (pixbuf));
printf ("%d lines %d chars\n",
- gtk_text_buffer_get_line_count (buffer),
- gtk_text_buffer_get_char_count (buffer));
+ gtk_text_buffer_get_line_count (buffer),
+ gtk_text_buffer_get_char_count (buffer));
+ /* Move cursor to start */
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
+ gtk_text_buffer_place_cursor (buffer, &iter);
+
gtk_text_buffer_set_modified (buffer, FALSE);
}
GdkPixbuf *pixbuf;
int i;
char *str;
+
+ /* FIXME this is broken if called twice on a buffer, since
+ * we try to create tags a second time.
+ */
tag = gtk_text_buffer_create_tag (buffer, "fg_blue");
g_object_unref (G_OBJECT (pixbuf));
printf ("%d lines %d chars\n",
- gtk_text_buffer_get_line_count (buffer),
- gtk_text_buffer_get_char_count (buffer));
+ gtk_text_buffer_get_line_count (buffer),
+ gtk_text_buffer_get_char_count (buffer));
+ /* Move cursor to start */
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
+ gtk_text_buffer_place_cursor (buffer, &iter);
+
gtk_text_buffer_set_modified (buffer, FALSE);
}